package com.info33.platform.doc.service.impl;

import cn.hutool.core.io.FileUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.info33.platform.common.constant.CustomizeYaml;
import com.info33.platform.common.constant.TableConstant;
import com.info33.platform.common.enums.FileSuffixEnum;
import com.info33.platform.common.mvc.vo.Result;
import com.info33.platform.doc.dao.DocFileDao;
import com.info33.platform.doc.dao.DocFileDetailDao;
import com.info33.platform.doc.dao.DocFileDirectoryDao;
import com.info33.platform.doc.dto.DocFileDTO;
import com.info33.platform.doc.dto.DocFileSearchDTO;
import com.info33.platform.doc.entity.DocFile;
import com.info33.platform.doc.entity.DocFileDetail;
import com.info33.platform.doc.entity.DocFileDirectory;
import com.info33.platform.doc.entity.DocFileUser;
import com.info33.platform.doc.service.DocFileDetailService;
import com.info33.platform.doc.service.DocFileDirectoryService;
import com.info33.platform.doc.service.DocFileService;
import com.info33.platform.doc.service.DocFileUserService;
import com.info33.platform.doc.util.enums.DocOperationTypeEnum;
import com.info33.platform.doc.util.enums.DocSpaceTypeEnum;
import com.info33.platform.doc.vo.DocFileStatisticsVO;
import com.info33.platform.doc.vo.DocFileVO;
import com.info33.platform.system.dao.SysDictionaryDao;
import com.info33.platform.system.entity.SysDictionary;
import com.info33.platform.system.vo.SysUserVO;
import net.coobird.thumbnailator.Thumbnails;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import ws.schild.jave.Encoder;
import ws.schild.jave.EncoderException;
import ws.schild.jave.MultimediaObject;
import ws.schild.jave.encode.AudioAttributes;
import ws.schild.jave.encode.EncodingAttributes;
import ws.schild.jave.encode.VideoAttributes;

import javax.imageio.ImageIO;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * @author admin
 */
@Service
@Transactional(rollbackFor = {Exception.class, Error.class})
public class DocFileServiceImpl extends ServiceImpl<DocFileDao, DocFile> implements DocFileService {

    @Autowired
    private DocFileDao docFileDao;

    @Autowired
    private DocFileDetailDao docFileDetailDao;

    @Autowired
    private DocFileUserService docFileUserService;

    @Autowired
    private DocFileDetailService docFileDetailService;

    @Autowired
    private CustomizeYaml customizeYaml;

    @Autowired
    private DocFileDirectoryService docFileDirectoryService;

    @Autowired
    private DocFileDirectoryDao docFileDirectoryDao;

    @Autowired
    private SysDictionaryDao sysDictionaryDao;

    @Override
    public IPage<DocFileVO> pageDocFileList(IPage<DocFileVO> page, DocFileSearchDTO docFileSearchDTO,
                                            SysUserVO currentUser) {
        return docFileDao.pageDocFileList(page, docFileSearchDTO, currentUser);
    }

    @Override
    public Result<?> upload(MultipartFile[] multipartFiles, DocFileDTO docFileDTO, Long tenantId) {
        List<DocFile> fileList = new ArrayList<DocFile>();
        DocFileDirectory docFileDirectory = docFileDirectoryDao.selectById(docFileDTO.getFileDirectoryId());
        switch (docFileDTO.getType()) {
            case 1:
                List<DocFileDetail> fileDetailList = new ArrayList<DocFileDetail>();
                String path = getPath(tenantId, docFileDirectory);
                for (MultipartFile multipartFile : multipartFiles) {
                    DocFile docFile = new DocFile();
                    BeanUtils.copyProperties(docFileDTO, docFile);
                    if (docFileDao.insert(docFile) > 0) {
                        fileList.add(docFile);
                        DocFileDetail docFileDetail = createFileDetail(path, docFileDirectory, multipartFile, docFile.getId(), docFileDTO.getOldName());
                        try {
                            multipartFile.transferTo(new File(customizeYaml.getUploadPath() + docFileDetail.getNewName()));
                        } catch (IllegalStateException | IOException e) {
                            e.printStackTrace();
                            return Result.error();
                        }
                        fileDetailList.add(docFileDetail);
                    } else {
                        return Result.error();
                    }
                }
                if (docFileDetailService.saveBatch(fileDetailList)) {
                    return defaultFileUser(fileList, tenantId, docFileDirectory.getType()) ? Result.ok() : Result.error();
                }
                return Result.error();
            case 2:
                DocFile docFile = new DocFile();
                BeanUtils.copyProperties(docFileDTO, docFile);
                if (docFileDao.insert(docFile) > 0) {
                    fileList.add(docFile);
                    DocFileDetail docFileDetail = new DocFileDetail();
                    docFileDetail.setFileId(docFile.getId());
                    docFileDetail.setFileNumber("FILE-" + System.currentTimeMillis());
                    docFileDetail.setOldName(docFileDTO.getOldName());
                    docFileDetail.setFileDesc(docFileDTO.getFileDesc());
                    if (docFileDetailDao.insert(docFileDetail) > 0) {
                        return defaultFileUser(fileList, tenantId, docFileDirectory.getType()) ? Result.ok() : Result.error();
                    }
                    return Result.error();
                }
                return Result.error();

            default:
                break;
        }
        return Result.error();
    }

    private DocFileDetail createFileDetail(String path, DocFileDirectory docFileDirectory,
                                           MultipartFile multipartFile, Long fileId, String oldName) {
        DocFileDetail docFileDetail = new DocFileDetail();
        docFileDetail.setFileId(fileId);
        docFileDetail.setFileNumber("FILE-" + System.currentTimeMillis());
        docFileDetail.setOldName(oldName);
        docFileDetail.setFileSuffix(FileUtil.getSuffix(docFileDetail.getOldName()));
        docFileDetail.setFileSize(Math.round((multipartFile.getSize() / 1048576.0) * 100.0) / 100.0);
        docFileDetail.setNewName(this.createFileName(path, docFileDetail.getFileSuffix()));
        return docFileDetail;
    }

    /**
     * 新增时给文档默认权限
     *
     * @param docSpaceTypeEnum
     //* @param docFile
     * @return
     */
    private Boolean defaultFileUser(List<DocFile> fileList, Long createBy, DocSpaceTypeEnum docSpaceTypeEnum) {
        List<DocFileUser> fileUserList = new ArrayList<DocFileUser>();
        for (DocFile docFile : fileList) {
            if (!DocSpaceTypeEnum.BUSINESS.equals(docSpaceTypeEnum)) {
                DocFileUser docFileUser = new DocFileUser();
                docFileUser.setFileId(docFile.getId());
                docFileUser.setType(4);
                docFileUser.setOperateType(DocOperationTypeEnum.EDIT);
                docFileUser.setUserId(createBy);
                fileUserList.add(docFileUser);

                docFileUser = new DocFileUser();
                docFileUser.setFileId(docFile.getId());
                docFileUser.setType(4);
                docFileUser.setOperateType(DocOperationTypeEnum.DELETE);
                docFileUser.setUserId(createBy);
                fileUserList.add(docFileUser);

                docFileUser = new DocFileUser();
                docFileUser.setFileId(docFile.getId());
                docFileUser.setType(4);
                docFileUser.setOperateType(DocOperationTypeEnum.DOWNLOAD);
                docFileUser.setUserId(createBy);
                fileUserList.add(docFileUser);

                docFileUser = new DocFileUser();
                docFileUser.setFileId(docFile.getId());
                docFileUser.setType(4);
                docFileUser.setOperateType(DocOperationTypeEnum.PREVIEW);
                docFileUser.setUserId(createBy);
                fileUserList.add(docFileUser);

                if (DocSpaceTypeEnum.PUBLIC.equals(docSpaceTypeEnum)) {
                    docFileUser = new DocFileUser();
                    docFileUser.setFileId(docFile.getId());
                    docFileUser.setType(5);
                    docFileUser.setOperateType(DocOperationTypeEnum.PREVIEW);
                    fileUserList.add(docFileUser);
                }
            } else {
                DocFileUser docFileUser = new DocFileUser();
                docFileUser.setFileId(docFile.getId());
                docFileUser.setType(5);
                docFileUser.setOperateType(DocOperationTypeEnum.PREVIEW);
                fileUserList.add(docFileUser);

                docFileUser = new DocFileUser();
                docFileUser.setFileId(docFile.getId());
                docFileUser.setType(5);
                docFileUser.setOperateType(DocOperationTypeEnum.DOWNLOAD);
                fileUserList.add(docFileUser);
            }
        }

        return docFileUserService.saveBatch(fileUserList);
    }

    /**
     * 创建一个新的文件名
     *
     * @param path   路径
     * @param suffix 新文件名的后缀
     * @return path/新文件名.入参后缀
     */
    private String createFileName(String path, String suffix) {
        return path + FileSuffixEnum.SLASH + System.currentTimeMillis() + UUID.randomUUID().toString().replace("-", "").substring(8)
                + FileSuffixEnum.DIAN + suffix;
    }

    @Override
    public DocFileVO getDetail(Long id) {
        return docFileDao.getDetail(id);
    }

    @Override
    public Result<?> editFile(MultipartFile[] multipartFiles, DocFileDTO docFileDTO, Long tenantId) {
        DocFile docFile = docFileDao.selectById(docFileDTO.getId());
        if (ObjectUtils.isEmpty(docFile)) {
            return Result.error("此条文档不存在");
        }
        switch (docFile.getType()) {
            case 1:
                List<DocFileDetail> fileDetailList = new ArrayList<DocFileDetail>();
                if (ObjectUtils.isEmpty(multipartFiles)) {
                    BeanUtils.copyProperties(docFileDTO, docFile);
                    if (docFileDao.updateById(docFile) > 0) {
                        DocFileDetail docFileDetail = docFileDetailDao.selectOne(new QueryWrapper<DocFileDetail>()
                                .eq("file_id", docFile.getId()).orderByDesc(TableConstant.CREATE_DATE).last(TableConstant.LIMIT_ONE));
                        docFileDetail.setOldName(docFileDTO.getOldName());
                        return docFileDetailDao.updateById(docFileDetail) > 0 ? Result.ok() : Result.error();
                    }
                    return Result.error();
                }
                DocFileDirectory docFileDirectory = docFileDirectoryDao.selectById(docFile.getFileDirectoryId());
                String path = getPath(tenantId, docFileDirectory);
                for (MultipartFile multipartFile : multipartFiles) {
                    BeanUtils.copyProperties(docFileDTO, docFile);
                    if (docFileDao.updateById(docFile) > 0) {
                        if (StringUtils.isEmpty(docFileDTO.getOldName())) {
                            docFileDTO.setOldName(multipartFile.getOriginalFilename());
                        }
                        DocFileDetail docFileDetail = createFileDetail(path, docFileDirectory,
                                multipartFile, docFile.getId(), docFileDTO.getOldName());
                        DocFileDetail fileDetail = docFileDetailDao.selectOne(new QueryWrapper<DocFileDetail>()
                                .eq("file_id", docFile.getId()).orderByDesc(TableConstant.CREATE_DATE).last(TableConstant.LIMIT_ONE));
                        Integer number = Integer.valueOf(fileDetail.getVersionNumber().substring(1)) + 1;
                        docFileDetail.setVersionNumber("v" + number);
                        try {
                            multipartFile.transferTo(new File(customizeYaml.getUploadPath() + docFileDetail.getNewName()));
                        } catch (IllegalStateException | IOException e) {
                            e.printStackTrace();
                            return Result.error();
                        }
                        fileDetailList.add(docFileDetail);
                    } else {
                        return Result.error();
                    }
                }
                return docFileDetailService.saveBatch(fileDetailList) ? Result.ok() : Result.error();
            case 2:
                BeanUtils.copyProperties(docFileDTO, docFile);
                if (docFileDao.updateById(docFile) > 0) {
                    DocFileDetail fileDetail = docFileDetailDao.selectOne(new QueryWrapper<DocFileDetail>()
                            .eq("file_id", docFile.getId()).orderByDesc(TableConstant.CREATE_DATE).last(TableConstant.LIMIT_ONE));
                    // 内容不发生改变
                    if (fileDetail.getFileDesc().equals(docFileDTO.getFileDesc())) {
                        fileDetail.setOldName(docFileDTO.getOldName());
                        return docFileDetailDao.updateById(fileDetail) > 0 ? Result.ok() : Result.error();
                    }
                    DocFileDetail docFileDetail = new DocFileDetail();
                    docFileDetail.setFileId(docFile.getId());
                    docFileDetail.setFileNumber("FILE-" + System.currentTimeMillis());
                    docFileDetail.setOldName(docFileDTO.getOldName());
                    docFileDetail.setFileDesc(docFileDTO.getFileDesc());
                    Integer number = Integer.valueOf(fileDetail.getVersionNumber().substring(1)) + 1;
                    docFileDetail.setVersionNumber("v" + number);
                    return docFileDetailDao.insert(docFileDetail) > 0 ? Result.ok() : Result.error();
                }
                return Result.error();
            default:
                break;
        }
        return Result.error();
    }

    /**
     * 获取文件路径
     *
     * @param tenantId
     * @param docFileDirectory
     * @return
     */
    private String getPath(Long tenantId, DocFileDirectory docFileDirectory) {
        String path = FileSuffixEnum.SLASH + "assets" + FileSuffixEnum.SLASH + docFileDirectory.getType();
        if (0 != docFileDirectory.getPid()) {
            //获取父级目录
            List<DocFileDirectory> fileDirectoryList = docFileDirectoryDao.selectList(new QueryWrapper<DocFileDirectory>()
                    .eq(TableConstant.TENANT_ID, tenantId).eq("type", docFileDirectory.getType()));
            List<String> parentName = docFileDirectoryService.queryParentDirectory(docFileDirectory.getPid(), fileDirectoryList);
            for (int i = parentName.size() - 1; i >= 0; i--) {
                path += FileSuffixEnum.SLASH + parentName.get(i);
            }
        }
        return path + FileSuffixEnum.SLASH + docFileDirectory.getName();
    }

    @Override
    public Result<?> removeFile(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return Result.error("请选择要删除的文档");
        }
        List<DocFileDetail> fileDetailList = new ArrayList<DocFileDetail>();
        for (Long id : ids) {
            List<DocFileDetail> list = docFileDetailDao.selectList(new QueryWrapper<DocFileDetail>().eq("file_id", id));
            fileDetailList.addAll(list);
        }
        List<String> pathList = new ArrayList<String>();
        for (DocFileDetail docFileDetail : fileDetailList) {
            if (!StringUtils.isEmpty(docFileDetail.getNewName())) {
                pathList.add(customizeYaml.getUploadPath() + docFileDetail.getNewName());
            }
        }
        //从服务器删除
        for (String path : pathList) {
            if (!new File(path).delete()) {
                return Result.error();
            }
        }
        //删除表中数据
        List<Long> fileDetailIds = fileDetailList.stream().map(d -> d.getId()).collect(Collectors.toList());
        if (docFileDetailDao.deleteBatchIds(fileDetailIds) > 0) {
            return docFileDao.deleteBatchIds(ids) > 0 ? Result.ok() : Result.error();
        }
        return Result.error();
    }

    @Override
    public Result<List<DocFileDetail>> businessUpload(MultipartFile[] multipartFiles, String module, Long tenantId) {
        if (ObjectUtils.isEmpty(multipartFiles)) {
            return Result.error("请上传资源");
        }
        if (StringUtils.isEmpty(module)) {
            return Result.error("模块名称不能为空");
        }
        DocFileDirectory docFileDirectory = docFileDirectoryDao.selectOne(new QueryWrapper<DocFileDirectory>()
                .eq("type", DocSpaceTypeEnum.BUSINESS).eq("name", module)
                .eq(TableConstant.TENANT_ID, tenantId));
        //创建目录
        DocFileDirectory yearDirectory = createDirectory(module, tenantId, docFileDirectory);
        if (ObjectUtils.isEmpty(yearDirectory)) {
            return Result.error("没有此目录");
        }
        List<DocFile> fileList = new ArrayList<DocFile>();
        List<DocFileDetail> fileDetailList = new ArrayList<DocFileDetail>();
        //默认标签
        SysDictionary sysDictionary = sysDictionaryDao.selectOne(new QueryWrapper<SysDictionary>().eq("indexes", "businessWord"));
        String path = getPath(tenantId, yearDirectory);
        for (MultipartFile multipartFile : multipartFiles) {
            DocFile docFile = new DocFile();
            docFile.setFileDirectoryId(yearDirectory.getId());
            docFile.setType(1);
            docFile.setDescription(module + "模块的描述");
            docFile.setLabelId(sysDictionary.getId().toString());
            if (docFileDao.insert(docFile) > 0) {
                fileList.add(docFile);
                DocFileDetail docFileDetail = new DocFileDetail();
                docFileDetail.setFileId(docFile.getId());
                docFileDetail.setFileNumber("FILE-" + System.currentTimeMillis());
                docFileDetail.setOldName(multipartFile.getOriginalFilename());
                docFileDetail.setFileSuffix(FileUtil.getSuffix(docFileDetail.getOldName()));
                docFileDetail.setFileSize(Math.round((multipartFile.getSize() / 1048576.0) * 100.0) / 100.0);
                docFileDetail.setNewName(this.createFileName(path, docFileDetail.getFileSuffix()));
                FileUtil.mkdir(new File(customizeYaml.getUploadPath() + path));
                try {
                    multipartFile.transferTo(new File(customizeYaml.getUploadPath() + docFileDetail.getNewName()));
                } catch (IllegalStateException | IOException e) {
                    e.printStackTrace();
                    return Result.error();
                }

                if (FileSuffixEnum.VIDEO.equals(FileSuffixEnum.getSuffixGroup(docFileDetail.getFileSuffix().toLowerCase()))) {
                    // mov 转 mp4
                    if (FileSuffixEnum.MOV_SUFFIX.equalsIgnoreCase(docFileDetail.getFileSuffix())) {
                        docFileDetail.setNewName(movToMp4(customizeYaml.getUploadPath(), docFileDetail.getNewName()));
                    }
                    docFileDetail.setImgUrl(docFileDetail.getNewName() + FileSuffixEnum.DIAN + FileSuffixEnum.PNG_SUFFIX);
                    if (Boolean.FALSE.equals(saveVideoImg(customizeYaml.getUploadPath() + docFileDetail.getImgUrl(), customizeYaml.getUploadPath() + docFileDetail.getNewName()))) {
                        docFileDetail.setImgUrl(null);
                    }
                }
                //压缩
                if (FileSuffixEnum.IMG.equals(FileSuffixEnum.getSuffixGroup(docFileDetail.getFileSuffix()))
                        && docFileDetail.getFileSize() > 1.0) {
                    try {
                        docFileDetail.setCompressImg(docFileDetail.getNewName() + FileSuffixEnum.DIAN + docFileDetail.getFileSuffix());
                        Thumbnails.of(customizeYaml.getUploadPath() + docFileDetail.getCompressImg())
                                //缩放比例
                                .scale(1f)
                                //图片质量
                                .outputQuality(0.5f)
                                .toFile(customizeYaml.getUploadPath() + docFileDetail.getNewName());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                fileDetailList.add(docFileDetail);
            } else {
                return Result.error();
            }
        }
        if (docFileDetailService.saveBatch(fileDetailList)) {
            return Boolean.TRUE.equals(defaultFileUser(fileList, tenantId, yearDirectory.getType())) ? Result.ok(fileDetailList) : Result.error();
        }
        return Result.error();
    }

    /**
     * 创建目录
     *
     * @param module
     * @param tenantId
     * @param docFileDirectory
     * @return
     */
    private DocFileDirectory createDirectory(String module, Long tenantId,
                                             DocFileDirectory docFileDirectory) {
        if (ObjectUtils.isEmpty(docFileDirectory)) {
            DocFileDirectory fileDirectory = docFileDirectoryDao.selectOne(new QueryWrapper<DocFileDirectory>()
                    .eq("type", DocSpaceTypeEnum.BUSINESS).eq("name", module).eq(TableConstant.TENANT_ID, 1));
            if (ObjectUtils.isEmpty(fileDirectory)) {
                return docFileDirectory;
            }
            List<DocFileDirectory> fileDirectoryList = docFileDirectoryDao.selectList(new QueryWrapper<DocFileDirectory>()
                    .eq(TableConstant.TENANT_ID, 1).eq("type", DocSpaceTypeEnum.BUSINESS));
            List<String> parentName = docFileDirectoryService.queryParentDirectory(fileDirectory.getPid(), fileDirectoryList);
            Long pid = 0L;
            for (int i = parentName.size() - 1; i >= 0; i--) {
                //依次建目录
                DocFileDirectory directory = docFileDirectoryDao.selectOne(new QueryWrapper<DocFileDirectory>()
                        .eq("type", DocSpaceTypeEnum.BUSINESS).eq("name", parentName.get(i))
                        .eq(TableConstant.TENANT_ID, tenantId));
                if (ObjectUtils.isEmpty(directory)) {
                    directory = new DocFileDirectory();
                    directory.setType(DocSpaceTypeEnum.BUSINESS);
                    directory.setPid(pid);
                    directory.setName(parentName.get(i));
                    if (docFileDirectoryDao.insert(directory) == 0) {
                        return null;
                    }
                }
                pid = directory.getId();
            }
            docFileDirectory = new DocFileDirectory();
            docFileDirectory.setType(DocSpaceTypeEnum.BUSINESS);
            docFileDirectory.setPid(pid);
            docFileDirectory.setName(fileDirectory.getName());
            if (docFileDirectoryDao.insert(docFileDirectory) == 0) {
                return null;
            }
        }
        //创建年份目录
        Integer year = Calendar.getInstance().get(Calendar.YEAR);
        DocFileDirectory yearDirectory = docFileDirectoryDao.selectOne(new QueryWrapper<DocFileDirectory>().eq(TableConstant.PID, docFileDirectory.getId()).eq("name", year.toString()));
        if (ObjectUtils.isEmpty(yearDirectory)) {
            yearDirectory = new DocFileDirectory();
            yearDirectory.setPid(docFileDirectory.getId());
            yearDirectory.setType(DocSpaceTypeEnum.BUSINESS);
            yearDirectory.setName(year.toString());
            if (docFileDirectoryDao.insert(yearDirectory) == 0) {
                return null;
            }
        }
        return yearDirectory;
    }

    @Override
    public List<DocFileVO> listWithUserInfo(String ids) {
        return docFileDao.listWithUserInfo(ids);
    }

    @Override
    public List<DocFileStatisticsVO> fileStatistics(SysUserVO currentUser) {
        return docFileDao.fileStatistics(currentUser);
    }

    /**
     * MOV -> MP4
     *
     * @param uploadPath yml 属性
     * @param fileName   db 库，文件路径
     * @return 新文件全路径
     */
    public static String movToMp4(String uploadPath, String fileName) {
        // 是 苹果 mov 视频，转换成 mp4
        AudioAttributes audio = new AudioAttributes();
        audio.setCodec("libmp3lame");
        // 设置比特率
        audio.setBitRate(800000);
        // 设置音频通道数
        audio.setChannels(1);
        // 设置采样率
        audio.setSamplingRate(44100);
        VideoAttributes video = new VideoAttributes();
        video.setCodec("libx264");
        video.setBitRate(3200000);
        video.setFrameRate(15);
        EncodingAttributes attrs = new EncodingAttributes();
        attrs.setOutputFormat("mp4");
        attrs.setAudioAttributes(audio);
        attrs.setVideoAttributes(video);
        Encoder encoder = new Encoder();
        String newMp4Name = fileName + "." + FileSuffixEnum.MP_4_SUFFIX;
        try {
            encoder.encode(new MultimediaObject(new File(uploadPath + fileName)), new File(uploadPath + newMp4Name), attrs);
        } catch (EncoderException e) {
            e.printStackTrace();
        }
        // 删除旧视频
        FileUtil.del(uploadPath + fileName);
        return newMp4Name;
    }


    /**
     * 根据视频路径，保存视频前几帧的图片
     *
     * @param targetPath 目标路径（全路径），精确到 .jpg
     * @param sourcePath 源路径（全路径），视频路径
     */
    public static boolean saveVideoImg(String targetPath, String sourcePath) {
        try (FFmpegFrameGrabber ff = new FFmpegFrameGrabber(new File(sourcePath))) {
            ff.start();
            Frame frame;
            if (ff.getLengthInFrames() > 51) {
                // 获取帧，避免出现全黑图片
                ff.setFrameNumber(50);
            }
            frame = ff.grabImage();
            // 创建 BufferedImage 对象、 图片后缀、目标路径
            ImageIO.write(new Java2DFrameConverter().getBufferedImage(frame), FileSuffixEnum.PNG_SUFFIX, new File(targetPath));
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

}